"""
Weather-related tools for FastMCP
"""

from fastmcp import FastMCP, Context
from typing import Optional
import json


class WeatherTools:
    """Weather-related tools for FastMCP."""

    # Simulated weather data for demonstration
    WEATHER_DATA = {
        "london": {
            "temperature": 15,
            "condition": "Cloudy",
            "humidity": 80,
            "wind_speed": 12,
            "pressure": 1013,
            "visibility": 10,
        },
        "paris": {
            "temperature": 18,
            "condition": "Sunny",
            "humidity": 60,
            "wind_speed": 8,
            "pressure": 1020,
            "visibility": 15,
        },
        "tokyo": {
            "temperature": 22,
            "condition": "Rainy",
            "humidity": 90,
            "wind_speed": 15,
            "pressure": 1008,
            "visibility": 5,
        },
        "newyork": {
            "temperature": 20,
            "condition": "Partly Cloudy",
            "humidity": 70,
            "wind_speed": 10,
            "pressure": 1015,
            "visibility": 12,
        },
        "sydney": {
            "temperature": 25,
            "condition": "Sunny",
            "humidity": 55,
            "wind_speed": 6,
            "pressure": 1022,
            "visibility": 20,
        },
    }

    def __init__(self, mcp: FastMCP):
        self.mcp = mcp

    def register(self):
        """Register all weather tools with FastMCP."""
        self.mcp.tool(
            name="get_weather",
            description="Get current weather information for a city",
            tags={"weather", "information", "public"},
        )(self.get_weather)

        self.mcp.tool(
            name="compare_weather",
            description="Compare weather between two cities",
            tags={"weather", "comparison", "analysis", "public"},
        )(self.compare_weather)

        self.mcp.tool(
            name="get_weather_forecast",
            description="Get a simulated 5-day weather forecast for a city",
            tags={"weather", "forecast", "planning", "public"},
        )(self.get_weather_forecast)

        self.mcp.tool(
            name="weather_alerts",
            description="Check for weather alerts and recommendations",
            tags={"weather", "alerts", "safety", "public"},
        )(self.weather_alerts)

    @staticmethod
    async def get_weather(city: str, ctx: Context, units: str = "celsius") -> dict:
        """Get weather information for a specified city."""
        await ctx.info(f"Looking up weather for {city}")

        city_lower = city.lower().replace(" ", "")

        if city_lower in WeatherTools.WEATHER_DATA:
            weather = WeatherTools.WEATHER_DATA[city_lower].copy()

            # Convert temperature if needed
            if units.lower() == "fahrenheit":
                weather["temperature"] = round(weather["temperature"] * 9 / 5 + 32, 1)
                weather["unit"] = "°F"
            else:
                weather["unit"] = "°C"

            weather["city"] = city.title()
            weather["data_source"] = "simulated"

            await ctx.info("Weather data retrieved successfully")
            return weather
        else:
            # Generate default weather for unknown cities
            default_weather = {
                "city": city.title(),
                "temperature": 20,
                "condition": "Unknown",
                "humidity": 70,
                "wind_speed": 10,
                "pressure": 1013,
                "visibility": 10,
                "unit": "°C" if units.lower() == "celsius" else "°F",
                "data_source": "default",
                "note": "City not found in database, showing default values",
            }

            if units.lower() == "fahrenheit":
                default_weather["temperature"] = 68  # 20°C in Fahrenheit

            await ctx.warning(f"City '{city}' not found, returning default weather")
            return default_weather

    @staticmethod
    async def compare_weather(ctx: Context, city1: str, city2: str) -> dict:
        """Compare weather conditions between two cities."""
        await ctx.info(f"Comparing weather between {city1} and {city2}")

        # Get weather for both cities
        weather1 = await WeatherTools.get_weather(city1, ctx, "celsius")
        weather2 = await WeatherTools.get_weather(city2, ctx, "celsius")

        # Calculate differences
        temp_diff = weather1["temperature"] - weather2["temperature"]
        humidity_diff = weather1["humidity"] - weather2["humidity"]

        comparison = {
            "city1": weather1,
            "city2": weather2,
            "comparison": {
                "temperature_difference": {
                    "value": round(temp_diff, 1),
                    "warmer_city": (
                        city1 if temp_diff > 0 else city2 if temp_diff < 0 else "equal"
                    ),
                },
                "humidity_difference": {
                    "value": round(humidity_diff, 1),
                    "more_humid_city": (
                        city1
                        if humidity_diff > 0
                        else city2 if humidity_diff < 0 else "equal"
                    ),
                },
                "condition_comparison": {
                    "city1_condition": weather1["condition"],
                    "city2_condition": weather2["condition"],
                },
            },
        }

        await ctx.info("Weather comparison completed")
        return comparison

    @staticmethod
    async def get_weather_forecast(ctx: Context, city: str) -> dict:
        """Get a 5-day weather forecast for a specified city."""
        await ctx.info(f"Generating forecast for {city}")

        # Get current weather as base
        current = await WeatherTools.get_weather(city, ctx, "celsius")

        # Generate forecast (simulated)
        forecast_days = []
        base_temp = current["temperature"]

        for day in range(1, 6):
            # Simulate temperature variation
            temp_variation = (day % 3 - 1) * 3  # -3, 0, +3 pattern
            forecasted_temp = base_temp + temp_variation

            # Simulate different conditions
            conditions = ["Sunny", "Partly Cloudy", "Cloudy", "Rainy", "Sunny"]

            forecast_day = {
                "day": f"Day {day}",
                "temperature": round(forecasted_temp, 1),
                "condition": conditions[day - 1],
                "humidity": current["humidity"] + (day % 2) * 10 - 5,
                "wind_speed": current.get("wind_speed", 10) + (day % 3),
                "precipitation_chance": min(max(day * 15, 0), 80),
            }
            forecast_days.append(forecast_day)

        forecast = {
            "city": current["city"],
            "current_weather": current,
            "forecast": forecast_days,
            "data_source": "simulated",
            "forecast_days": 5,
        }

        await ctx.info("5-day forecast generated")
        return forecast

    @staticmethod
    def weather_alerts(city: str) -> dict:
        """Check for weather alerts and provide recommendations."""
        city_lower = city.lower().replace(" ", "")

        alerts = []
        recommendations = []

        if city_lower in WeatherTools.WEATHER_DATA:
            weather = WeatherTools.WEATHER_DATA[city_lower]

            # Check temperature alerts
            if weather["temperature"] > 30:
                alerts.append("High temperature warning")
                recommendations.append("Stay hydrated and avoid prolonged sun exposure")
            elif weather["temperature"] < 0:
                alerts.append("Freezing temperature warning")
                recommendations.append("Dress warmly and be careful of icy conditions")

            # Check wind alerts
            if weather["wind_speed"] > 20:
                alerts.append("High wind warning")
                recommendations.append(
                    "Secure loose objects and avoid outdoor activities"
                )

            # Check visibility alerts
            if weather["visibility"] < 8:
                alerts.append("Low visibility warning")
                recommendations.append("Drive carefully and use headlights")

            # Check humidity alerts
            if weather["humidity"] > 85:
                alerts.append("High humidity warning")
                recommendations.append("Stay in air-conditioned areas if possible")

        return {
            "city": city.title(),
            "alerts_count": len(alerts),
            "alerts": alerts,
            "recommendations": recommendations,
            "alert_level": (
                "high" if len(alerts) > 2 else "medium" if len(alerts) > 0 else "low"
            ),
        }
